home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / raytrace / pov / source / point.c < prev    next >
C/C++ Source or Header  |  1993-07-29  |  8KB  |  276 lines

  1. /****************************************************************************
  2. *                point.c
  3. *
  4. *  This module implements the point & spot light source primitive.
  5. *
  6. *  from Persistence of Vision Raytracer
  7. *  Copyright 1993 Persistence of Vision Team
  8. *---------------------------------------------------------------------------
  9. *  NOTICE: This source code file is provided so that users may experiment
  10. *  with enhancements to POV-Ray and to port the software to platforms other 
  11. *  than those supported by the POV-Ray Team.  There are strict rules under
  12. *  which you are permitted to use this file.  The rules are in the file
  13. *  named POVLEGAL.DOC which should be distributed with this file. If 
  14. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  15. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  16. *  Forum.  The latest version of POV-Ray may be found there as well.
  17. *
  18. * This program is based on the popular DKB raytracer version 2.12.
  19. * DKBTrace was originally written by David K. Buck.
  20. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  21. *
  22. *****************************************************************************/
  23.  
  24. #include "frame.h"
  25. #include "vector.h"
  26. #include "povproto.h"
  27.  
  28. METHODS Light_Source_Methods =
  29.   { 
  30.   All_Light_Source_Intersections,
  31.   Inside_Light_Source, Light_Source_Normal,
  32.   Copy_Light_Source,
  33.   Translate_Light_Source, Rotate_Light_Source,
  34.   Scale_Light_Source, Transform_Light_Source, Invert_Light_Source,
  35.   Destroy_Light_Source
  36. };
  37.  
  38. static DBL cubic_spline PARAMS(( DBL low,DBL high,DBL pos));
  39.  
  40. int All_Light_Source_Intersections (Object, Ray, Depth_Stack)
  41. OBJECT *Object;
  42. RAY *Ray;
  43. ISTACK *Depth_Stack;
  44.   {
  45.   if (((LIGHT_SOURCE *)Object)->Children != NULL)
  46.     if (Ray_In_Bounds (Ray, ((LIGHT_SOURCE *)Object)->Children->Bound))
  47.       if (All_Intersections (((LIGHT_SOURCE *)Object)->Children, Ray, Depth_Stack))
  48.         return (TRUE);
  49.  
  50.   return (FALSE);
  51.   }
  52.  
  53. int Inside_Light_Source (IPoint, Object)
  54. VECTOR *IPoint;
  55. OBJECT *Object;
  56.   {
  57.   if (((LIGHT_SOURCE *)Object)->Children != NULL)
  58.     if (Inside_Object (IPoint, ((LIGHT_SOURCE *)Object)->Children))
  59.       return (TRUE);
  60.  
  61.   return (FALSE);
  62.   }
  63.  
  64. void Light_Source_Normal (Result, Object, IPoint)
  65. OBJECT *Object;
  66. VECTOR *Result, *IPoint;
  67.   {
  68.   if (((LIGHT_SOURCE *)Object)->Children != NULL)
  69.     Normal (Result, ((LIGHT_SOURCE *)Object)->Children,IPoint);
  70.   }
  71.  
  72. void Translate_Light_Source (Object, Vector)
  73. OBJECT *Object;
  74. VECTOR *Vector;
  75.   {
  76.   VAddEq (((LIGHT_SOURCE *) Object)->Center, *Vector);
  77.   VAddEq (((LIGHT_SOURCE *) Object)->Points_At, *Vector);
  78.  
  79.   Translate_Object (((LIGHT_SOURCE *)Object)->Children, Vector);
  80.   }
  81.  
  82. void Rotate_Light_Source (Object, Vector)
  83. OBJECT *Object;
  84. VECTOR *Vector;
  85.   {
  86.   TRANSFORM Trans;
  87.  
  88.   Compute_Rotation_Transform (&Trans, Vector);
  89.   Transform_Light_Source(Object, &Trans);
  90.   }
  91.  
  92. void Scale_Light_Source (Object, Vector)
  93. OBJECT *Object;
  94. VECTOR *Vector;
  95.   {
  96.   TRANSFORM Trans;
  97.  
  98.   Compute_Scaling_Transform (&Trans, Vector);
  99.   Transform_Light_Source(Object, &Trans);
  100.   }
  101.  
  102. void Invert_Light_Source (Object)
  103. OBJECT *Object;
  104.   {
  105.   Invert_Object (((LIGHT_SOURCE *)Object)->Children);
  106.   }
  107.  
  108. void Transform_Light_Source (Object, Trans)
  109. OBJECT *Object;
  110. TRANSFORM *Trans;
  111.   {
  112.   MTransPoint (&((LIGHT_SOURCE *) Object)->Center,
  113.     &((LIGHT_SOURCE *) Object)->Center, Trans);
  114.   MTransPoint (&((LIGHT_SOURCE *) Object)->Points_At,
  115.     &((LIGHT_SOURCE *) Object)->Points_At, Trans);
  116.   MTransPoint (&((LIGHT_SOURCE *) Object)->Axis1,
  117.     &((LIGHT_SOURCE *) Object)->Axis1, Trans);
  118.   MTransPoint (&((LIGHT_SOURCE *) Object)->Axis2,
  119.     &((LIGHT_SOURCE *) Object)->Axis2, Trans);
  120.   Transform_Object (((LIGHT_SOURCE *)Object)->Children, Trans);
  121.   }
  122.  
  123. void Destroy_Light_Source (Object)
  124. OBJECT *Object;
  125.   {
  126.   int i;
  127.  
  128.   if (((LIGHT_SOURCE *)Object)->Light_Grid != NULL) 
  129.     { 
  130.     for (i = 0; i < ((LIGHT_SOURCE *)Object)->Area_Size1; i++)
  131.       free(((LIGHT_SOURCE *)Object)->Light_Grid[i]);
  132.  
  133.     free(((LIGHT_SOURCE *)Object)->Light_Grid);
  134.     } 
  135.  
  136.   Destroy_Object (((LIGHT_SOURCE *)Object)->Children);
  137.   free (Object);
  138.   }
  139.  
  140. COLOUR **Create_Light_Grid (Size1, Size2)
  141. int Size1, Size2;
  142.   {
  143.   COLOUR **New;
  144.   int i;
  145.  
  146.   New = (COLOUR **)malloc (Size1 * sizeof (COLOUR *));
  147.   if (New == NULL)
  148.     MAError ("area light");
  149.  
  150.   for (i = 0; i < Size1; i++) 
  151.     {
  152.     New[i] = (COLOUR *)malloc (Size2 * sizeof (COLOUR));
  153.     if (New[i] == NULL)
  154.       MAError ("area light");
  155.     }
  156.  
  157.   return (New);
  158.   }
  159.  
  160. LIGHT_SOURCE *Create_Light_Source ()
  161.   {
  162.   LIGHT_SOURCE *New;
  163.  
  164.   if ((New = (LIGHT_SOURCE *) malloc (sizeof (LIGHT_SOURCE))) == NULL)
  165.     MAError ("light_source");
  166.  
  167.   INIT_OBJECT_FIELDS(New, LIGHT_OBJECT, &Light_Source_Methods)
  168.     New->Children = NULL;
  169.   New->No_Shadow_Flag = TRUE;
  170.  
  171.   Make_Colour(&New->Colour,1.0,1.0,1.0);
  172.   Make_Vector(&New->Center,0.0,0.0,0.0);
  173.   Make_Vector(&New->Points_At,0.0,0.0,1.0);
  174.   Make_Vector(&New->Axis1,0.0,0.0,1.0);
  175.   Make_Vector(&New->Axis2,0.0,1.0,0.0);
  176.   New->Coeff   = 10.0;
  177.   New->Radius  = 0.35;
  178.   New->Falloff = 0.35;
  179.   New->Next_Light_Source    = NULL;
  180.   New->Shadow_Cached_Object = NULL;
  181.   New->Light_Grid           = NULL;
  182.   New->Light_Type = POINT_SOURCE;
  183.   New->Area_Light = FALSE;
  184.   New->Jitter     = FALSE;
  185.   New->Track      = FALSE;
  186.   New->Area_Size1 = 0;
  187.   New->Area_Size2 = 0;
  188.   New->Adaptive_Level = 100;
  189.   return (New);
  190.   }
  191.  
  192. void *Copy_Light_Source (Old)
  193. OBJECT *Old;
  194.   {
  195.   LIGHT_SOURCE *New;
  196.   int i, j;
  197.  
  198.   New = Create_Light_Source ();
  199.   *New = *(LIGHT_SOURCE *)Old;
  200.  
  201.   New->Next_Light_Source = NULL;
  202.  
  203.   New->Children = Copy_Object (((LIGHT_SOURCE *)Old)->Children);
  204.  
  205.   if (((LIGHT_SOURCE *)Old)->Light_Grid != NULL) 
  206.     { 
  207.     New->Light_Grid = Create_Light_Grid (((LIGHT_SOURCE *)Old)->Area_Size1,
  208.       ((LIGHT_SOURCE *)Old)->Area_Size2);
  209.  
  210.     for (i = 0; i < ((LIGHT_SOURCE *)Old)->Area_Size1; i++)
  211.       for (j = 0; j < ((LIGHT_SOURCE *)Old)->Area_Size2; j++)
  212.       New->Light_Grid[i][j] = ((LIGHT_SOURCE *)Old)->Light_Grid[i][j];
  213.     } 
  214.  
  215.   return (New);
  216.   }
  217.  
  218. /* Cubic spline that has tangents of slope 0 at x == low and at x == high.
  219.    For a given value "pos" between low and high the spline value is returned */
  220. static DBL cubic_spline(low, high, pos)
  221. DBL low, high, pos;
  222.   {
  223.   /* Check to see if the position is within the proper boundaries */
  224.   if (pos < low)
  225.     return 0.0;
  226.   else if (pos > high)
  227.     return 1.0;
  228.   if (high == low)
  229.     return 0.0;
  230.  
  231.   /* Normalize to the interval 0->1 */
  232.   pos = (pos - low) / (high - low);
  233.  
  234.   /* See where it is on the cubic curve */
  235.   return (3 - 2 * pos) * pos * pos;
  236.   }
  237.  
  238. DBL Attenuate_Light (Light_Source, Light_Source_Ray)
  239. LIGHT_SOURCE *Light_Source;
  240. RAY *Light_Source_Ray;
  241.   {
  242.   DBL Len,costheta;
  243.   DBL Attenuation = 1.0;
  244.   VECTOR Spot_Direction;
  245.  
  246.   /* If this is a spotlight then attenuate based on the incidence angle */
  247.   if (Light_Source->Light_Type == SPOT_SOURCE) 
  248.     {
  249.     VSub(Spot_Direction, Light_Source->Points_At, Light_Source->Center);
  250.     VLength(Len, Spot_Direction);
  251.     if (Len > 0.0) 
  252.       {
  253.       VInverseScale(Spot_Direction, Spot_Direction, Len);
  254.       VDot(costheta, Light_Source_Ray->Direction, Spot_Direction);
  255.       costheta *= -1.0;
  256.       if (costheta > 0.0) 
  257.         {
  258.         Attenuation = pow(costheta, Light_Source->Coeff);
  259.         /* If there is a soft falloff region associated with the light then
  260.                do an interpolation of values between the hot center and the
  261.                direction at which light falls to nothing. */
  262.         if (Light_Source->Radius > 0.0)
  263.           Attenuation *= cubic_spline(Light_Source->Falloff,
  264.             Light_Source->Radius,
  265.             costheta);
  266.         /* printf("Atten: %lg\n", Attenuation); */
  267.         }
  268.       else
  269.         Attenuation = 0.0;
  270.       }
  271.     else
  272.       Attenuation = 0.0;
  273.     } 
  274.   return(Attenuation);
  275.   }    
  276.